<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 * @author   howe <howe1995@163.com>
 */

namespace App\Controller\Api\V1;

use App\Constant\ApiCodeEnum;
use App\Constant\TalkEventConstant;
use App\Event\TalkEvent;
use App\Exception\BusinessException;
use App\Middleware\CaptchaMiddleware;
use App\Middleware\JWTAuthMiddleware;
use App\Services\UserService;
use App\Support\Traits\AesUtil;
use Exception;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Psr\Http\Message\ResponseInterface;

/**
 * 授权相关控制器.
 */
#[Controller('/api/v1/auth')]
class AuthController extends CController
{
    use AesUtil;

    #[Inject]
    protected UserService $userService;

    // #[Middlewares([CaptchaMiddleware::class])]
    #[RequestMapping(path: 'login', methods: 'post')]
    public function login()
    {
        $params = $this->request->inputs(['mobile', 'password', 'code']);
        $this->validate($params, [
            'mobile' => 'required|phone',
            'password' => 'required',
            'code' => 'required|digits:4|int',
        ]);

        try {
            $user = $this->userService->login($params['mobile'], $params['password']);
        } catch (Exception $exception) {
            logInfo('login_error', $exception->getMessage());
            throw new BusinessException(ApiCodeEnum::FAILED_DEFAULT);
        }
        event()->dispatch(new TalkEvent([
            'who' => TalkEventConstant::WHO_USER,
            'action' => TalkEventConstant::ACTION_LOGIN,
            'data' => [
                'from' => $user['id'],
                'message' => '你的好友' . $user['nickname'] . '登录了',
                'status' => 0,
            ],
        ]));
        return $this->success($user, $this->request, ApiCodeEnum::SERVICE_LOGIN_SUCCESS);
    }

    /**
     * 退出登录接口.
     */
    #[Middlewares([JWTAuthMiddleware::class])]
    #[RequestMapping(path: 'logout', methods: 'post')]
    public function logout(): ResponseInterface
    {
        if ($this->guard()->check()) {
            $user = $this->guard()->user();
            event()->dispatch(new TalkEvent([
                'who' => TalkEventConstant::WHO_USER,
                'action' => TalkEventConstant::ACTION_LOGIN,
                'data' => [
                    'from' => $user['id'],
                    'message' => '你的好友' . $user['nickname'] . '退出了',
                    'status' => 0,
                ],
            ]));
            $this->guard()->logout();
            return $this->success([], $this->request);
        }
        throw new BusinessException(ApiCodeEnum::SERVICE_LOGIN_ERROR, '账号不存在或密码填写错误！');
    }

    /**
     * 账号注册接口.
     */
    #[Middlewares([CaptchaMiddleware::class])]
    #[RequestMapping(path: 'register', methods: 'post')]
    public function register(): ResponseInterface
    {
        $params = $this->request->all();

        $this->validate($params, [
            'wechat' => 'required|min:4|max:20',
            'nickname' => 'required|max:20',
            'mobile' => 'required|regex:/^1[3-9]\d{9}$/',
            'password' => 'required|min:6',
        ]);

        $data = $this->userService->register($params);
        return $this->success($data, $this->request, ApiCodeEnum::SERVICE_REGISTER_SUCCESS);
    }

    /**
     * 账号找回接口.
     */
    #[RequestMapping(path: 'forget', methods: 'post')]
    public function forget(): ResponseInterface
    {
        $params = $this->request->inputs(['mobile', 'password', 'sms_code']);

        $this->validate($params, [
            'mobile' => 'required|phone',
            'password' => 'required|max:16',
            'sms_code' => 'required|digits:6',
        ]);

        $isTrue = $this->userService->resetPassword($params['mobile'], $params['password']);
        if (! $isTrue) {
            throw new BusinessException(ApiCodeEnum::CLIENT_NOT_FOUND_HTTP_ERROR, '重置密码失败！');
        }

        return $this->success([], $this->request);
    }

    /**
     * 授权刷新接口.
     */
    #[RequestMapping(path: 'refresh', methods: 'post')]
    public function refresh(): ResponseInterface
    {
        if ($this->guard()->guest()) {
            // 刷新失败，没有登陆
            throw new BusinessException(ApiCodeEnum::CLIENT_TOKEN_UNAVAILABLE, '刷新失败！');
        }

        return $this->success([
            'type' => 'Bearer',
            'token' => $this->guard()->refresh(),
            'expire' => $this->guard()->getJwtManager()->getTtl(),
        ], $this->request);
    }

    /**
     * 用户主页.
     */
    #[Middlewares([JWTAuthMiddleware::class])]
    #[RequestMapping(path: '{keywords}/home', methods: 'get')]
    public function home(string $keywords)
    {
        $params = $this->request->all();
        $params['keywords'] = $keywords;
        $params['user'] = $this->user();
        $data = $this->userService->home($params);
        return $this->success($data, $this->request);
    }

    /**
     * 用户信息.
     */
    #[Middlewares([JWTAuthMiddleware::class])]
    #[RequestMapping(path: '{id}/info', methods: 'get')]
    public function info(int $id)
    {
        $params = $this->request->all();
        $params['id'] = $id;
        $params['user'] = $this->user();
        $data = $this->userService->info($params);
        return $this->success($data, $this->request);
    }

    /**
     * 更新用户信息.
     */
    #[Middlewares([JWTAuthMiddleware::class])]
    #[RequestMapping(path: 'update', methods: 'put')]
    public function update()
    {
        $params = $this->request->all();
        $params['user'] = $this->user();
        $data = $this->userService->update($params);
        return $this->success($data, $this->request);
    }

    #[Middlewares([JWTAuthMiddleware::class])]
    #[RequestMapping(path: 'moments', methods: 'get')]
    public function moments()
    {
        $params = $this->request->all();
        $params['user'] = $this->user();
        $this->validate($params, [
            'user_id' => 'required',
            'page' => 'integer|min:1',
            'limit' => 'integer|min:1|max:20',
        ]);
        $data = $this->userService->moments($params);
        return $this->setPageInfo($data[0])->success($data[1], $this->request);
    }

    /**
     * 充值
     * @throws ValidationException
     * @throws BusinessException
     */
    #[Middlewares([JWTAuthMiddleware::class])]
    public function charge(Request $request): JsonResponse
    {
        $this->validate($request, [
            'money' => 'required|integer|min:1|max:10000',
        ]);
        $this->userService->charge($this->params);
        return $this->success([], $request);
    }
}
